/* Copyright VirtuaMUnstaz (http://virtuamunstaz.de/) */
/* NetHack may be freely redistributed.  See license for details.  */

/*
 * PSP Event handling.
 */


#include "pspevent.h"

#define BUTTONMASK(button) (1 << button)
#define PRESS(button) (buttons |= BUTTONMASK(button))
#define RELEASE(button) (buttons ^= BUTTONMASK(button))
#define IS_PRESSED(button) (buttons & BUTTONMASK(button))

#define MODE_LEVELS 2

enum modes {
  MODE_0, MODE_1, MODE_2,
  MODE_COUNT
};

/* PSP buttons and special button combinations */
enum buttons {
  TRIANGLE, CIRCLE, CROSS, SQUARE, T_LEFT, T_RIGHT, DOWN, LEFT, UP, RIGHT, SELECT, START, HOME, HOLD,
  DOWNLEFT, DOWNRIGHT, UPLEFT, UPRIGHT,
  BUTTON_COUNT
};

/* button mapping */
static SDL_Event mapping[MODE_COUNT][BUTTON_COUNT];


static SDL_Joystick *joystick;
static int buttons;


/* function prototypes */
void map_key(SDL_Event *event, SDLKey key, SDLMod mod, Uint16 code);
void PSP_TranslateEvents();

/* HACK: to reduce changes in the original files */
void intron() { }
void introff() { }

/* set keyym for a specific PSP key in an event */
void map_key(SDL_Event *event, SDLKey key, SDLMod mod, Uint16 code) {
  event->key.keysym.sym = key;
  event->key.keysym.mod = mod;
  event->key.keysym.unicode = code;
}

/*
 * Initialization of PSP specific hardware (joystick) and the button mapping
 *
 */
void psp_event_init() {


  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
  SDL_JoystickEventState(SDL_ENABLE);
  SDL_EventState(SDL_JOYBUTTONUP, SDL_IGNORE);
  SDL_EventState(SDL_JOYBUTTONDOWN, SDL_IGNORE);
  joystick = SDL_JoystickOpen(0);


  map_key(&mapping[MODE_0][DOWN], SDLK_DOWN, KMOD_NONE, 0);
  map_key(&mapping[MODE_0][LEFT], SDLK_LEFT, KMOD_NONE, 0);
  map_key(&mapping[MODE_0][UP], SDLK_UP, KMOD_NONE, 0);
  map_key(&mapping[MODE_0][RIGHT], SDLK_RIGHT, KMOD_NONE, 0);
  map_key(&mapping[MODE_0][DOWNLEFT], SDLK_b, KMOD_NONE, 'b');
  map_key(&mapping[MODE_0][DOWNRIGHT], SDLK_n, KMOD_NONE, 'n');
  map_key(&mapping[MODE_0][UPLEFT], SDLK_y, KMOD_NONE, 'y');
  map_key(&mapping[MODE_0][UPRIGHT], SDLK_u, KMOD_NONE, 'u');

  map_key(&mapping[MODE_0][CROSS], SDLK_n, KMOD_NONE, 'n');
  map_key(&mapping[MODE_0][SQUARE], SDLK_o, KMOD_NONE, 'o');
  map_key(&mapping[MODE_0][TRIANGLE], SDLK_SPACE, KMOD_NONE, ' ');
  map_key(&mapping[MODE_0][CIRCLE], SDLK_y, KMOD_NONE, 'y');
  map_key(&mapping[MODE_0][SELECT], SDLK_s, KMOD_NONE, 's');
  map_key(&mapping[MODE_0][START], SDLK_a, KMOD_NONE, 'a');

  map_key(&mapping[MODE_0][T_RIGHT], SDLK_w, KMOD_NONE, 'w');
  map_key(&mapping[MODE_0][T_LEFT], SDLK_r, KMOD_NONE, 'r');




}

/*
* We have to poll for ourself as the PSP SDL code does not
 * auto-repeat and does not create events for simultaneous pressed
 * buttons.
 */
int PSP_PollEvent(SDL_Event *ev) {
  SDL_JoystickUpdate();
  PSP_TranslateEvents();
  return SDL_PollEvent(ev);
}

void PSP_TranslateEvents() {
  int mode, button;
  SDL_Event *event;

  mode = MODE_0;

  for(button = 0; button <= HOLD; button++) {
    // ignore mode keys (T_LEFT always, T_RIGHT if mode > 0)
    if(button == T_LEFT) continue;
    if(mode > MODE_0 && button == T_RIGHT) continue;

    switch(SDL_JoystickGetButton(joystick, button)) {
      case SDL_PRESSED:
	// already pressed? ignore now
	if(IS_PRESSED(button)) continue;
	// this is an ugly hack to get diagnonal keys, only KEYDOWN is fired
	if(button == DOWN && SDL_JoystickGetButton(joystick, LEFT) == SDL_PRESSED) {
	  event = &mapping[mode][DOWNLEFT];
	  PRESS(LEFT);
	} else if(button == DOWN && SDL_JoystickGetButton(joystick, RIGHT) == SDL_PRESSED) {
	  event = &mapping[mode][DOWNRIGHT];
	  PRESS(RIGHT);
	} else if(button == UP && SDL_JoystickGetButton(joystick, LEFT) == SDL_PRESSED) {
	  event = &mapping[mode][UPLEFT];
	  PRESS(LEFT);
	} else if(button == UP && SDL_JoystickGetButton(joystick, RIGHT) == SDL_PRESSED) {
	  event = &mapping[mode][UPRIGHT];
	  PRESS(RIGHT);
	} else {
	  event = &mapping[mode][button];
	}


	PRESS(button);
	break;
      case SDL_RELEASED:
	// still released? ignore now
	if(!IS_PRESSED(button)) continue;
	event = &mapping[mode][button];

    event->type = SDL_KEYUP;
    event->key.type = SDL_KEYUP;
    event->key.state = SDL_RELEASED;

	RELEASE(button);
	break;
    }
    SDL_PushEvent(event);
  }
}




